package br.edu.unifei.mestrado.greedy.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.edu.unifei.mestrado.commons.graph.NodeWrapper;
import br.edu.unifei.mestrado.commons.partition.AbstractPartition;
import br.edu.unifei.mestrado.commons.partition.AbstractPartitionIndex;
import br.edu.unifei.mestrado.greedy.SubSet;


//o código da classe SetHelper foi colocado nessa classe
public class Partition extends AbstractPartition {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	/**
	 * Estrutura de dados PARTITION.
	 * 
	 *id_set, SubSet
	 */
	private Map<Integer, SubSet> sets = new HashMap<Integer, SubSet>();
	
	private Map<Integer, Integer> numberOfNodeOfSet = new HashMap<Integer, Integer>();

	private Frontier frontier = null;
	
	public Partition(int level, int k, AbstractPartitionIndex index) {
		super(level, k, index);
		for (int set = 1; set <= k; set++) {
			//inicializa os sets
			sets.put(set, new SubSet(set));
		}
		
		frontier = new Frontier();
	}

	public SubSet getSetById(Integer setId) {
		return sets.get(setId);
	}

	public Map<Integer, SubSet> getSets() {
		return sets;
	}

	public List<NodeWrapper> includeNodesToFrontier(NodeWrapper baseNode) {
		return frontier.includeNodesToFrontier(baseNode);
	}

	public int getFrontierCount() {
		return frontier.getVertices().size();
	}

	/**
	 * Atualiza o valor de Diff para cada set e vértice da fronteira.
	 * 
	 * @param k
	 */
	public void updateDiffFor() {
		for (SubSet set : this.getSets().values()) { // sets
			set.updateDiff(this.getSets().values(), frontier.getVertices());// TODO: verificar a performance
			// setResult.updateDiff(set, justIncluded);
			// TODO: atualizar o diff para os outros nós também, que podem ter sido influenciados pelos
			// justIncluded
		}
	}

	public void removeFromFrontier(NodeWrapper node) {
		frontier.remove(node);
	}

	public void printNForSet(final SubSet setTmp) {
		logger.debug("N    for " + setTmp + ": {}", new Object() {
			@Override
			public String toString() {
				StringBuffer b = new StringBuffer();
				for (NodeWrapper node : frontier.getVertices()) {
					b.append(node.getId() + "=" + setTmp.getN(node) + ", ");
				}
				return b.toString();
			}
		});
	}

	public void printFrontier() {
		frontier.printFrontier();
	}

	@Override
	public void addNodeToSet(int setId, NodeWrapper node) {
		super.addNodeToSet(setId, node);

		Integer count = numberOfNodeOfSet.get(setId);
		if(count == null) {
			count = 1;
		} else {
			count++;
		}
		numberOfNodeOfSet.put(setId, count);
	}
	
	@Override
	public void removeNodeFromSet(int setId, NodeWrapper node) {
		super.removeNodeFromSet(setId, node);
		
		Integer count = numberOfNodeOfSet.get(setId);
		if(count != null) {
			count--;
			numberOfNodeOfSet.put(setId, count);
		}
	}
	
	public int getAmountOfNodes(int setId) {
		Integer count = numberOfNodeOfSet.get(setId);
		if(count != null) {
			return count;
		}
		return 0;
	}

	//no SetHelper aqui estava os prints de N, diff, minVal, int e ext
}
